package vip.guzb.sample.threadpool.step02;

import java.util.HashSet;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;

/**
 * 拥有多个线程的线程池任务执行器
 *
 * @author 顾志兵
 * @mail ipiger@163.com
 * @since 2024-04-09
 */
public class MultiThreadPoolExecutor implements Executor {

    // 线程池
    private final Set<TaskRunner> runnerPool = new HashSet<>();

    // 任务队列
    private final Queue<Runnable> tasks = new LinkedBlockingDeque<>();

    // 单个线程最大空闲时间，单位：毫秒
    private int maxIdleMilliSeconds = 3000;

    // 核心线程数
    private int coreThreadCount = 1;

    // 最大线程数
    private int maxThreadCount = 3;

    public MultiThreadPoolExecutor() {
        // 初始化核心线程
        for (int i = 0; i < coreThreadCount; i++) {
            addRunner(true);
        }
    }

    private void addRunner(boolean isCoreRunner) {
        TaskRunner runner = new TaskRunner(isCoreRunner);
        runnerPool.add(runner);
        runner.start();
    }

    @Override
    public void execute(Runnable task) {
        tasks.add(task);
        addRunnerIfRequired();
    }

    // 视情况增加线程数，这里简化为当任务数超过线程数的两倍时，就增加线程
    private void addRunnerIfRequired() {
        if (tasks.size() <= 2 * runnerPool.size()) {
            return;
        }
        // 未达到最大线程数时，可增加执行线程
        if (runnerPool.size() < maxThreadCount) {
            synchronized (this) {
                if (runnerPool.size() < maxThreadCount) {
                    addRunner(false);
                }
            }
        }
    }

    public void printAllRunners() {
        for (TaskRunner runner : runnerPool) {
            System.out.println(runner.toString());
        }
    }

    class TaskRunner extends Thread {
        // 是否为核心线程
        private final boolean coreRunner;

        // 已空闲的毫秒数
        private long idleMilliseconds = 0;

        TaskRunner(boolean coreRunner) {
            this.coreRunner = coreRunner;
        }

        @Override
        public void run() {
            Runnable task;
            while (true) {
                task = tasks.poll();
                if (task != null) {
                    task.run();
                    continue;
                }
                try {
                    TimeUnit.MILLISECONDS.sleep(10);
                    idleMilliseconds += 10;
                    if(coreRunner) {
                        continue;
                    }
                    if (idleMilliseconds > maxIdleMilliSeconds) {
                        // 超过最大空间时间，线程结束，并从池中移徐本线程
                        runnerPool.remove(this);
                        break;
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    break;
                }
            }
        }

        @Override
        public String toString() {
            return String.format("线程名：%s, 是否为核心线程：%s, 空闲时长：%s 毫秒", getName(), coreRunner, idleMilliseconds);
        }
    }
}
